/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package at.tugraz.hidipic.web.execution;

import at.tugraz.hidipic.model.*;
import at.tugraz.hidipic.web.execution.dto.FileResult;
import at.tugraz.hidipic.web.execution.dto.GenericResult;
import at.tugraz.hidipic.web.execution.dto.ParamResult;
import java.io.File;
import java.util.*;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Component;

/**
 *
 * @author mario
 */
@Component
public class DefaultMethodImpl implements MethodExecution {

    protected String path;
    protected final Logger LOG = Logger.getLogger(this.getClass());
    protected SubProject subProject;
    protected Date startDate;
    protected String methodName;
    protected ConfigurationObject config;
    protected Method method;
    protected Set<InputDataItem> inputData;
    protected User creator;
    protected HibernateTemplate hibernateTemplate;

    @Autowired
    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }

    public void setCreator(User creator) {
        this.creator = creator;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public void setConfig(ConfigurationObject config) {
        this.config = config;
    }

    public void setInputData(Set<InputDataItem> inputData) {
        this.inputData = inputData;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public void setSubProject(SubProject subProject) {
        this.subProject = subProject;
    }

    /**
     * fires start event
     *
     * @param message
     */
    protected void fireStartEvent(String message) {
        hibernateTemplate.save(createEvent(message, 0));
    }

    /**
     * fires error event
     *
     * @param message
     */
    protected void fireErrorEvent(String message) {
        hibernateTemplate.save(createEvent(message, 1));
    }

    /**
     * fires success event
     *
     * @param message
     */
    protected void fireSuccessEvent(String message) {
        hibernateTemplate.save(createEvent(message, 2));
    }

    /**
     * creates an event for firing
     *
     * @param msg
     * @param type
     * @return the event
     */
    protected Event createEvent(String msg, int type) {
        Event event = new Event();
        event.setCreationDate(new Date());
        String text = msg + " | " + this.methodName + " | " + this.startDate.toString();
        event.setText(text);
        event.setSubProject(this.subProject);
        event.setType(type);
        return event;
    }

    /**
     * returns a file-object for an url
     *
     * @param url
     * @return
     */
    protected File getFile(String url) {
        try {
            File file = new File(path + url);
            return file;
        } catch (Exception e) {
            LOG.error(e);
        }
        return null;
    }

    /**
     * create and persist output data for a method
     *
     * @param res
     * @param data
     */
    protected void createOutputData(Result res, List<GenericResult> data) {
        try {
            for (GenericResult g : data) {
                OutputDataItem odi = new OutputDataItem();
                if (g instanceof FileResult) {
                    FileResult fr = (FileResult) g;
                    odi.setUrl(fr.getUrl());
                } else if (g instanceof ParamResult) {
                    ParamResult pr = (ParamResult) g;
                    odi.setVal(pr.getValue());
                }
                UUID uuid = UUID.randomUUID();
                Long randId = uuid.getMostSignificantBits();
                String id = "f" + randId.toString();
                odi.setName(id);
                odi.setTitle(g.getName());
                odi.setCreator(this.creator);
                odi.setCreated(new Date());
                odi.setResult(res);
                hibernateTemplate.save(odi);
            }
        } catch (Exception e) {
            fireErrorEvent("There was an error creating the outputdata.");
        }
    }

    /**
     * method for creating a result and persisting it from data
     *
     * @param data
     */
    public void createResult(List<GenericResult> data) {
        try {
            Result res = new Result();
            res.setMethod(this.method);
            res.setConfig(this.config);
            res.setInputData(this.inputData);
            res.setCreationDate(new Date());
            res.setSubProject(this.subProject);
            res.setCreator(this.creator);
            hibernateTemplate.save(res);
            this.config.setResult(res);
            hibernateTemplate.merge(this.config);
            createOutputData(res, data);
            fireSuccessEvent("Result generation was successfull.");
        } catch (Exception e) {
            LOG.error(e);
            fireErrorEvent("There was an error creating the result.");
        }
    }

    @Override
    public void run(Map<String, Object> data) {
        // do execution
    }
}
